use rust_decimal::Decimal;

use self::error::CalcResult;

mod ast;
mod error;
mod lexer;
mod parser;
mod token;

pub fn calculate(input: &str) -> CalcResult<Decimal> {
   let mut parser = parser::Parser::new(input)?;
   let ast = parser.parse()?;
   Ok(ast.eval())
}

#[cfg(test)]
mod tests {
   use rust_decimal::dec;

   use super::*;

   #[test]
   fn test_calculate() {
      assert_eq!(calculate("1 + 2").unwrap(), dec!(3));
      assert_eq!(calculate("1 - 2").unwrap(), dec!(-1));
      assert_eq!(calculate("-1 / 2").unwrap(), dec!(-0.5));
      assert_eq!(calculate("-2 ^ 3").unwrap(), dec!(-8));
      assert_eq!(calculate("3-(2+3)*2 - 1 * (-3*3)").unwrap(), dec!(2));
   }
}
